/*
 * symbol_table.h
 *
 *  Created on: Dec 12, 2010
 *      Author: cpy.prefers.you@gmail.com
 */

#ifndef SYMBOL_TABLE_H_
#define SYMBOL_TABLE_H_

#define HASH_TABLE_SIZE 65537 //Prime[6543]
#define MESSAGE_LEN            0xff
#define TOKEN_LEN              0x3ff
#define NUM_PRINT_LEN          0x0f

#define TRUE    "\"true"
#define FALSE   "\"false"

enum ListOfPrecedences
{
    PRECEDENCE_UNKNOWN_TYPE,
    PRECEDENCE_MULOP,
    PRECEDENCE_ADDOP,
    PRECEDENCE_EQUAL_COMPOP,
    PRECEDENCE_INEQUAL_COMPOP = PRECEDENCE_EQUAL_COMPOP,
    NUMBER_OF_PRECEDENCES
};

enum ListOfSymbolTypes
{
    TYPE_UNKNOWN,
    TYPE_EMPTY,
    TYPE_NUMBER,
    TYPE_BOOLEAN_TRUE,
    TYPE_BOOLEAN_FALSE,
    TYPE_WORD,
    TYPE_DEREF,
    TYPE_NAME,
    TYPE_LIST,
    TYPE_ARRAY,
    TYPE_PROCEDURE,
    TYPE_FUNCTION,
    TYPE_ADDOP,
    TYPE_MULOP,
    TYPE_EQUAL_COMPOP,
    TYPE_INEQUAL_COMPOP,
    TYPE_COLON,
    TYPE_BACKQUOTE,
    TYPE_L_PARENTHESIS,
    TYPE_R_PARENTHESIS,
    NUMBER_OF_SYMBOL_TYPES
};

typedef struct SymbolType
{
    char Name[TOKEN_LEN];
    int Type;
    void *FunctionPointer;                /* for commands & procedures */
    int Precedence;                       /* for operators */
    struct SymbolType *Value;
    struct SymbolListType *Element;       /* for lists & arrays */
    struct SymbolListType *ParameterList; /* for user-defined procedures */
    struct SymbolListType *ProcedureBody; /* for user-defined procedures */
}   Symbol_T;

typedef struct SymbolListType
{
    Symbol_T *Symbol;
    struct SymbolListType *Next;
}   SymbolList_T;

typedef struct SymbolStackType
{
    SymbolList_T *SymbolList;
}   SymbolStack_T;

typedef void (*ProcedureFP)(SymbolList_T**);
typedef void (*FunctionFP)(SymbolList_T**, Symbol_T*);
typedef void (*OperationFP)(Symbol_T*, Symbol_T*);

extern Symbol_T *NewSymbol();
extern SymbolList_T *NewSymbolList();
extern SymbolStack_T *NewSymbolStack();
extern void CopySymbol(Symbol_T **Dest, Symbol_T *Source);
extern void CopySymbolList(SymbolList_T **Dest, SymbolList_T *Source);
extern void FreeSymbol(Symbol_T **Symbol);
extern void FreeSymbolList(SymbolList_T **SymbolList);
extern void FreeSymbolStack(SymbolStack_T **SymbolStack);
extern void SymbolTableInit();
extern Symbol_T *InsertSymbol(Symbol_T *Symbol);
extern Symbol_T *LookupName(char *Name);
extern void UpdateValue(Symbol_T *Symbol);
extern void RemoveSymbol(char *Name);
extern int IsEmptyStack(SymbolStack_T *SymbolStack);
extern void PopStack(SymbolStack_T *SymbolStack, Symbol_T *Symbol);
extern void PushStack(SymbolStack_T *SymbolStack, Symbol_T *Symbol);
extern void InsertLocalVariable(Symbol_T *Symbol);
extern void RemoveLocalVariable(char *Name);
extern void RemoveAllLocalVariable();

#define InsertKeyword(_Name, _Type) \
        InsertSymbol(&(Symbol_T){ .Name = _Name, .Type = TYPE_KEYWORD })

#define InsertOperator(_Name, _Precedence, _Type, _Func ) \
        InsertSymbol(&(Symbol_T){ .Name = _Name, .Type = _Type, .FunctionPointer = _Func, .Precedence = _Precedence })

#define InsertFunction(_Name, _Func) \
        InsertSymbol(&(Symbol_T){ .Name = _Name, .Type = TYPE_FUNCTION, .FunctionPointer = (void *)_Func })

#define InsertProcedure(_Name, _Func) \
        InsertSymbol(&(Symbol_T){ .Name = _Name, .Type = TYPE_PROCEDURE, .FunctionPointer = (void *)_Func })


#endif /* SYMBOL_TABLE_H_ */
